import os, threading, logging
import struct
import string
import subprocess
import traceback
from socket import socket
from vdsAgentLogic import DataRetriverBase, AgentLogicBase, HypercallBase
#from ctypes import *

class IncomingMessageTypes:
        Credentials = 11

class hcProxyXP(HypercallBase):
    def __init__(self):
        self._sock = None

    def hcInit(self):
        """return 0 on success"""
        return 0 # TODO

    def hcTerm(self):
        """Terminate hc. return 0 on success"""
        return 0

    def hcSend(self,msg_type, msg):
      if self._sock:
        logging.debug("hcProxyXP::hcSend before sending %d'%s'"%(msg_type,msg))
        streamed_msg, m_len = self.buildHcMsg(msg_type, msg)
#        retval = HypercallLib.hcSend(HypercallLib.HC_BALLOON, streamed_msg, m_len)
        logging.debug("hcProxyXP::hcSend streamed:'%s' len %d"%(streamed_msg, m_len))
        retval = self._sock.sendall(streamed_msg) # TODO
        logging.debug("hcProxyXP::hcSend after sending '%s'"%(retval))
        return 0 # TODO return error code

    def hcRecv(self):
        retval = ''
        try:
            logging.debug("hcProxyXP::hcRecv() - before")
            logging.debug("DDD should block on socket input")
            ans = self._sock.recv(1024)
#            flag, ans = HypercallLib.hcRecvC()
            logging.debug("hcProxyXP::hcRecv() - after")
#            if flag != 0:
#                raise Exception("HypercallLib.hcRecv() returned errcode %d"%(flag))
            retval = ans
            logging.debug("HypercallLib.hcRecv() retval = %s"%(repr(retval)))
        except:
            logging.error("FakeVdsAgent::__init__() - '%s'"%(traceback.format_exc()))
            retval = ''
        return retval

    def setSocket(self, sock):
        self._sock = sock


class CommandHandlerFake:
    def __init__(self, agent):
        logging.debug("CommandHandlerFake::__init__() - entered")
        self._agent = agent

    def parsePortString(self, portStr):
        intPorts = []
        try:
            ports = [portStr[0:5], portStr[5:10], portStr[10:15], portStr[15:20], portStr[20:25]]
            intPorts = [int(x) for x in ports]
        except:
            logging.error("CommandHandlerFake::parsePortString('%s') failed - '%s'"%(portStr, traceback.format_exc()))
        return intPorts

    def handleCommand(self, command):
        initloPath = False
        logging.debug("CommandHandlerFake::handleCommand('%s') - entered"%(command))
        try:
            if command == 'lock screen':
                logging.debug(command)
            elif command == 'log off':
                logging.debug(command)
            elif command[:len('client ip')] == 'client ip':
                ip = socket.inet_ntoa(struct.pack('L',int(command[len('client ip')+1:])))
                logging.debug("Client connected (IP = %s)" % ip);
                #hcProxyXP().hcSend(messageType.clientIp, "") #TODO
            elif command[:len('redagent')] == 'redagent':
                try:
                    agent, sid, prog, params = command.split(None, 3)
                    logging.debug("Agent command: %s %s (sid = %s)" % (prog, params, sid));
                    exe_name = None
                    if prog == 'reschange':
                        # TODO: Need to find exe in a better way!
                        exe_name = 'reschange.exe'
                    if exe_name:
                        cmd = "%s %s" % (exe_name, params)
                        logging.debug("Agent is executing: %s" % (cmd))
                        result = subprocess.call(cmd)
                        logging.debug("Sending ACK: %s %d" % (sid, result))
                        #hcProxyXP().hcSend(messageType.agentCmd, "%s %d" % (sid, result)) #TODO
                    else:
                        logging.error("Uknown agent command: %s" % command)
                except:
                    logging.error("Agent command exception - %s" % (traceback.format_exc()))
                    #hcProxyXP().hcSend(messageType.agentCmd, "%s %d" % (sid, -66)) #TODO
            elif command.startswith('shutdown'):
                logging.debug("CommandHandlerFake::handleCommand ..."+command)
            elif command.startswith('login'):
                logging.debug("CommandHandlerWin::handleCommand .... login")
                try:
                    credentials = command[6:]
                    logging.debug("CommandHandlerWin::handleCommand credentials = %s"%(repr(credentials)))
                    self._agent.dr._activeUser = credentials
                except:
                    logging.debug("CommandHandlerWin::handleCommand - %s" %(traceback.format_exc()))
            elif command.startswith('refresh'):
                try:
                    logging.debug("CommandHandlerWin::handleCommand .... refreshing data")
                    self._agent.sendUserInfo(True)
                    self._agent.sendAppList()
                    self._agent.sendInfo()
                except:
                    logging.debug("CommandHandlerWin::handleCommand - %s" %(traceback.format_exc()))
            elif command[:3] == 'NOC':
                # Just don't let anything else get this command.
                # NOC = NO Change (default settings)
                pass
            elif command[:3] == 'TCP':
                ports = self.parsePortString(command[3:])
                logging.debug(command + str(ports))
            elif command[:3] == 'UDP':
                ports = self.parsePortString(command[3:])
                logging.debug(command + str(ports))
            else:
                tmp=[]
                tmp = struct.unpack("I",command[:4])
                val = socket.ntohl(int(tmp[0]))
                if val == IncomingMessageTypes.Credentials:
                    logging.debug("TODO: " + command[4:])
                else:
                    logging.debug("CommandHandlerFake::handleCommand  : unknown incoming command type ")

        except:
            logging.error("CommandHandlerFake::handleCommand('%s') failed - '%s'"%(command, traceback.format_exc()))


class FakeDataRetriver(DataRetriverBase):
    def __init__(self):
        self._activeUser = 'None'

    def getMachineName(self):
        retval = ''
        if os.environ.has_key("COMPUTERNAME"):
            retval = os.environ["COMPUTERNAME"]
        return retval

    def getDomainName(self):
        retval = ''
        if os.environ.has_key("LOGONSERVER"):
            retval = os.environ["LOGONSERVER"]
        return retval

    def getOsVersion(self):
        return 'FakeGuest'

    def getAllNetworkInterfaces(self):
        retval = ''
        try:
            retval = string.join(socket.gethostbyname_ex(socket.gethostname())[2]," ")
        except:
            logging.error("FakeDataRetriver:getAllNetworkInterfaces - failed\n%s"%(traceback.format_exc()))
        return retval

    def getApplications(self):
        retval = ['no apps']
        return retval

    def getAvailableRAM(self):
        """In Mb, as string"""
        return '100'

    def getGeneralInfo(self):
        pass

    def getUsers(self):
        total_list=[]
        return total_list

    def getActiveUser(self):
        return self._activeUser


class FakeVdsAgent(AgentLogicBase):
    def __init__(self, logFileName=""):
        if logFileName:
            self.log_file_name = logFileName
        else:
            self.log_file_name = "/tmp/guest.log"
        AgentLogicBase.__init__(self)
        logging.debug("ddd try")
        self.hc = hcProxyXP()
        self.dr = FakeDataRetriver()
        self.commandHandler =  CommandHandlerFake(self)

    def run(self):
        logging.debug("FakeVdsAgent:: run() entered")
#        self.baseRun() # I don't like baseRun, so I'm recoding it here
        logging.debug("AgentLogicBase:: baseRun() entered")
        if self.hc.hcInit():
            errMsg = "AgentLogicBase::baseRun() - Failed initializing the HypercallLib, check the Hypercall driver installation"
            logging.error(errMsg)
            raise errMsg
        else:
            pass
        self.listenThread = threading.Thread(target=self.doListen,
                                             name='AgentListen')
        self.workThread = threading.Thread(target=self.doWork,
                                           name='AgentWork')
        self.listenThread.setDaemon(True)
        self.workThread.setDaemon(True)
        self.listenThread.start()
        self.workThread.start()

    def stop(self):
        logging.debug("FakeVdsAgent:: stop() entered")
        self.baseStop()
        logging.debug("FakeVdsAgent:: stop() sent stop event")



vdsAgent = FakeVdsAgent
